package com.handu.luna.core.domain.order;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import javax.persistence.Entity;
import javax.persistence.Lob;
import javax.persistence.PostLoad;
import javax.persistence.Transient;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.validation.constraints.Min;

import com.handu.luna.core.domain.goods.Brand;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.data.jpa.domain.Specification;

import com.handu.luna.core.domain.BasePersistentDomain;
import com.handu.luna.core.domain.search.OrderSearch;
import com.handu.luna.core.domain.user.User;
/**
 * 系统分单规则：
 *
 *	系统会根据“品牌类型”来对购买的商品订单进行分单。
 *
 *	现在分三个类型：自有品牌、素缕品牌、代购品牌。
 *	
 *	订单分单形式，主订单信息+子订单，商品从属于子订单。
 *
 *	主订单：包含所有子订单的信息数据和，当所有子订单都发货后，才显示已发货。
 *
 *	子订单：可多个，根据品牌类型和用户购买商品决定，子订单的状态只有“是否发货”状态。子订单会存储属于自己的优惠数据。
 *	子订单构成规则：
 *	主订单订单号后面加01、02、03、04..区分。
 *
 */
@Entity
public class OrderInfo  extends BasePersistentDomain<OrderInfoRepository>{
	
	public enum OrderStatus{
		UNCONFIRMED("未确认"),CONFIRMED("已确认"),CANCEL("已关闭"),RETURNS("已退款");	
	    public String description;	    
	    OrderStatus(final String description) {
	        this.description = description;
	    }
	}
	
	public enum PaymentStatus{
		NONPAYMENT("未付款"),ACCOUNTPAID("已付款");	
	    public String description;	    
	    PaymentStatus(final String description) {
	        this.description = description;
	    }
	}
	
	public enum DeliveryStatus{
		NONSHIPPED("未发货"),SHIPPED("已发货"),SOMESHIPPED("部分发货"),RECEIVED("已收货");	
	    public String description;	    
	    DeliveryStatus(final String description) {
	        this.description = description;
	    }
	}
	
	public enum OrderSource{
		WEBPAGE("网页"),MOBILEPHONE("手机客户端"),WAP("WAP站");	
	    public String description;	    
	    OrderSource(final String description) {
	        this.description = description;
	    }
	}
	
	public enum Purchasing{
		ISPURCHASING("代购订单"),NOTPURCHASING("非代购订单");
		public String description;
		Purchasing(final String description){
			this.description = description;
		}
	}
	
	////////////////是否已删除////////////////////////////	

	private boolean deleted;
    
	////////////////订单基本信息////////////////////////////
	
	private String orderNumber;//订单号
	
	private boolean isParent = false;//是否是父订单 默认否
	
	private String parentNumber;//父订单单号
	
	private long userId;//购货人ID --父订单存储
	
	private String username;//购货人姓名--父订单存储
	
	@Transient
	private User user;//购货人
	
	private String paymentMode; //支付方式 暂时设为string --父订单存储
	
	private String shippingMethod;//配送方式 暂时定为string--父订单存储
	
	private Date overbookingTime; //下单时间--父订单存储
	
	private Date paymentTime;//支付时间--父订单存储
	
	private Date updateStatusTime; //修改订单状态的时间
	
	private OrderStatus orderStatus;//订单状态
	
	private PaymentStatus paymentStatus;//支付状态
	
	private DeliveryStatus deliveryStatus;//发货状态  子订单只有发货状态 且发货状态只有是否发货两种状态  父订单三种状态均具有
	
	private Purchasing purchasing; //是否代购 --父订单存储
	
	private OrderSource orderSource;//订单来源 --父订单存储
	
	private Date deliveryTime;//发货时间 --子订单
	
	private String deliveryNumber;//发货单号 ---子订单
	
	//////////////////费用信息 -- 父子订单均有  父订单存储全部  子订单存储自己的///////////////////////////////////
	
	private BigDecimal orderAmount;//订单金额
	
	private BigDecimal goodsAmount;//商品金额
	
	private BigDecimal paymentAmount;//支付金额
	
	private BigDecimal discountAmount;//折扣金额
	
	private BigDecimal redpacketsAmount;//红包金额
	
	private BigDecimal couponAmount;//优惠券金额
	
	private BigDecimal integrationAmount;//积分金额
	
	@Min(value=0)
	private BigDecimal freightAmount;//运费
	
	
	/////////////////收货人信息 --父订单存储////////////////////////////////////////
	
	private String consignee;//收货人
	
	private String address;//收货人地址
	
	private String telephone;//收货人电话
	
	private String cellphone;//收货人手机
	
	private String postcode;//收货人邮编
	
	/////////////////其他信息////////////////////////////////////////
	
	private String customerMessage;//客户留言 --父订单存储
	
	@Lob
	private String serviceNote;//客服备注

    private Brand.BrandType brandType;
	
	@Transient
	private List<OrderDetail> saleItems;
	
	@Transient
	private List<OrderInfo> children;

    //页面显示基本信息及收货人信息时调用
    @Transient
    private OrderInfo parentOrder;

    @Transient
    private BigDecimal restPaymentAmount;//后台订单详情界面的应支付金额


	public String getOrderNumber() {
		return orderNumber;
	}

	public void setOrderNumber(String orderNumber) {
		this.orderNumber = orderNumber;
	}

	public boolean getIsParent() {
		return isParent;
	}

    public OrderInfo getParentOrder() {
        return parentOrder;
    }

    public void setParentOrder(OrderInfo parentOrder) {
        this.parentOrder = parentOrder;
    }

    public void setIsParent(boolean isParent) {
		this.isParent = isParent;
	}

	public String getParentNumber() {
		return parentNumber;
	}

	public void setParentNumber(String parentNumber) {
		this.parentNumber = parentNumber;
	}

	public long getUserId() {
		return userId;
	}

	public void setUserId(long userId) {
		this.userId = userId;
	}
	
	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public User getUser() {
		return user;
	}

	public void setUser(User user) {
		this.user = user;
	}

	public String getPaymentMode() {
		return paymentMode;
	}

	public void setPaymentMode(String paymentMode) {
		this.paymentMode = paymentMode;
	}

	public String getShippingMethod() {
		return shippingMethod;
	}

	public void setShippingMethod(String shippingMethod) {
		this.shippingMethod = shippingMethod;
	}

	public Date getOverbookingTime() {
		return overbookingTime;
	}

	public void setOverbookingTime(Date overbookingTime) {
		this.overbookingTime = overbookingTime;
	}

	public Date getPaymentTime() {
		return paymentTime;
	}

	public void setPaymentTime(Date paymentTime) {
		this.paymentTime = paymentTime;
	}

	public OrderStatus getOrderStatus() {
		return orderStatus;
	}

	public void setOrderStatus(OrderStatus orderStatus) {
		this.orderStatus = orderStatus;
	}

	public PaymentStatus getPaymentStatus() {
		return paymentStatus;
	}

	public void setPaymentStatus(PaymentStatus paymentStatus) {
		this.paymentStatus = paymentStatus;
	}

	public DeliveryStatus getDeliveryStatus() {
		return deliveryStatus;
	}

	public void setDeliveryStatus(DeliveryStatus deliveryStatus) {
		this.deliveryStatus = deliveryStatus;
	}

	public OrderSource getOrderSource() {
		return orderSource;
	}

	public void setOrderSource(OrderSource orderSource) {
		this.orderSource = orderSource;
	}

	public Date getDeliveryTime() {
		return deliveryTime;
	}

	public void setDeliveryTime(Date deliveryTime) {
		this.deliveryTime = deliveryTime;
	}

	public String getDeliveryNumber() {
		return deliveryNumber;
	}

	public void setDeliveryNumber(String deliveryNumber) {
		this.deliveryNumber = deliveryNumber;
	}

	public BigDecimal getOrderAmount() {
		return orderAmount;
	}

	public void setOrderAmount(BigDecimal orderAmount) {
		this.orderAmount = orderAmount;
	}

	public BigDecimal getGoodsAmount() {
		return goodsAmount;
	}

	public void setGoodsAmount(BigDecimal goodsAmount) {
		this.goodsAmount = goodsAmount;
	}

	public BigDecimal getPaymentAmount() {
		return paymentAmount;
	}

	public void setPaymentAmount(BigDecimal paymentAmount) {
		this.paymentAmount = paymentAmount;
	}

	public BigDecimal getDiscountAmount() {
		return discountAmount;
	}

	public void setDiscountAmount(BigDecimal discountAmount) {
		this.discountAmount = discountAmount;
	}

	public BigDecimal getRedpacketsAmount() {
		return redpacketsAmount;
	}

	public void setRedpacketsAmount(BigDecimal redpacketsAmount) {
		this.redpacketsAmount = redpacketsAmount;
	}

	public BigDecimal getCouponAmount() {
		return couponAmount;
	}

	public void setCouponAmount(BigDecimal couponAmount) {
		this.couponAmount = couponAmount;
	}

	public BigDecimal getIntegrationAmount() {
		return integrationAmount;
	}

	public void setIntegrationAmount(BigDecimal integrationAmount) {
		this.integrationAmount = integrationAmount;
	}

	public BigDecimal getFreightAmount() {
		return freightAmount;
	}

	public void setFreightAmount(BigDecimal freightAmount) {
		this.freightAmount = freightAmount;
	}

	public String getConsignee() {
		return consignee;
	}

	public void setConsignee(String consignee) {
		this.consignee = consignee;
	}

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

	public String getTelephone() {
		return telephone;
	}

	public void setTelephone(String telephone) {
		this.telephone = telephone;
	}

	public String getCellphone() {
		return cellphone;
	}

	public void setCellphone(String cellphone) {
		this.cellphone = cellphone;
	}

	public String getPostcode() {
		return postcode;
	}

	public void setPostcode(String postcode) {
		this.postcode = postcode;
	}

	public String getCustomerMessage() {
		return customerMessage;
	}

	public void setCustomerMessage(String customerMessage) {
		this.customerMessage = customerMessage;
	}

	public String getServiceNote() {
		return serviceNote;
	}

	public void setServiceNote(String serviceNote) {
		this.serviceNote = serviceNote;
	}

	public List<OrderDetail> getSaleItems() {
		if(!isParent && (saleItems == null||saleItems.size()==0)){
			saleItems = context.getOrderDetailRepository().findByOrderNumber(this.orderNumber);
		}
		return saleItems;
	}
    //初始化父子订单的一些属性
    // 初始化父订单  将该父订单下的所有商品查找并赋值
    // 初始化子订单  将该子订单的父订单查找找 并且 将该子订单下的所有商品查找并赋值
    @PostLoad
    public void initializeRedundancy (){
        if(!isParent){
            this.setParentOrder(context.getOrderInfoRepository().findByOrderNumber(this.parentNumber).get(0));
            saleItems = context.getOrderDetailRepository().findByOrderNumber(this.orderNumber);
            if (saleItems != null){
                for(int i =0 ;i<saleItems.size() ;i++){
                    saleItems.get(i).getGoods().setBrand(context.getBrandRepository().findOne(saleItems.get(i).getGoods().getBrandId()));;
                }
            }

        }else{
            List<OrderInfo> childs = context.getOrderInfoRepository().findAllChildsByOrderNumber(this.orderNumber);
            List<OrderDetail> details = new ArrayList<OrderDetail>();
            if (CollectionUtils.isNotEmpty(childs)){
                for (OrderInfo order :childs){
                    List<OrderDetail> childsDetails = context.getOrderDetailRepository().findByOrderNumber(order.getOrderNumber());
                    for(int i =0 ;i<childsDetails.size() ;i++){
                        childsDetails.get(i).getGoods().setBrand(context.getBrandRepository().findOne(childsDetails.get(i).getGoods().getBrandId()));;
                    }
                    details.addAll(childsDetails);
                }
            }else{
                List<OrderDetail> childsDetails = context.getOrderDetailRepository().findByOrderNumber(this.getOrderNumber());
                for(int i =0 ;i<childsDetails.size() ;i++){
                    childsDetails.get(i).getGoods().setBrand(context.getBrandRepository().findOne(childsDetails.get(i).getGoods().getBrandId()));;
                }
                details.addAll(childsDetails);
            }

            this.saleItems = details;
        }
    }

	public void setSaleItems(List<OrderDetail> saleItems) {
		this.saleItems = saleItems;
	}
	
	public List<OrderInfo> getChildren() {
		if(isParent && (children == null||children.size()==0)){
			children = context.getOrderInfoRepository().findNotDeletedChildsByOrderNumber(this.orderNumber);
		}
		return children;
	}

	public void delete() {
		this.setDeleted(true);
		context.getOrderInfoRepository().save(this);
	}
	
	public void setChildren(List<OrderInfo> children) {
		this.children = children;
	}

	public boolean isDeleted() {
		return deleted;
	}

	public void setDeleted(boolean deleted) {
		this.deleted = deleted;
	}
	
	
	
	public Purchasing getPurchasing() {
		return purchasing;
	}

	public void setPurchasing(Purchasing purchasing) {
		this.purchasing = purchasing;
	}
	
	
	public Date getUpdateStatusTime() {
		return updateStatusTime;
	}

	public void setUpdateStatusTime(Date updateStatusTime) {
		this.updateStatusTime = updateStatusTime;
	}

    public Brand.BrandType getBrandType() {
        return brandType;
    }

    public void setBrandType(Brand.BrandType brandType) {
        this.brandType = brandType;
    }

    public BigDecimal getRestPaymentAmount() {
        if (isParent?(this.paymentStatus.name().equals("ACCOUNTPAID")):(this.getParentOrder().getPaymentStatus().name().equals("ACCOUNTPAID"))){
            return BigDecimal.valueOf(0);
        }else{
            return this.getOrderAmount()
                    .subtract(this.getIntegrationAmount()==null?BigDecimal.valueOf(0):this.getIntegrationAmount())
                    .subtract(this.getRedpacketsAmount()==null?BigDecimal.valueOf(0):this.getRedpacketsAmount())
                    .subtract(this.getCouponAmount()==null?BigDecimal.valueOf(0):this.getCouponAmount());
        }
    }

    public void setRestPaymentAmount(BigDecimal restPaymentAmount) {
        this.restPaymentAmount = restPaymentAmount;
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	////////***********父订单是否是代购订单 需在生成订单的时候设定，否则在查询的时候再去设置查询条件显得太过于麻烦 所以在订单中又加入了一个是否是代购订单的属性*******///////
	///////************另外 此处自动生成的父订单设定的是否代购属性并没有根据订单中的商品的品牌属性进行相应的设置，只是单纯的设置为是代购订单或者非代购订单*********////////
	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	public OrderInfo(String orderNumber,  long userId,String username,
			String paymentMode, String shippingMethod, Date overbookingTime,
			Date paymentTime,OrderSource source ,Purchasing purchasing,
            OrderStatus orderStatus,PaymentStatus paymentStatus,DeliveryStatus deliveryStatus,
			 String consignee, String address,
			String cellphone, String postcode,
            BigDecimal orderAmount, BigDecimal goodsAmount,
            BigDecimal paymentAmount, BigDecimal discountAmount,
            BigDecimal redpacketsAmount, BigDecimal couponAmount,
            BigDecimal integrationAmount, BigDecimal freightAmount,
            Brand.BrandType brandType) {
		super();
		this.orderNumber = orderNumber;
		this.isParent = true;
		this.userId = userId;
		this.username = username;
		this.paymentMode = paymentMode;
		this.shippingMethod = shippingMethod;
		this.overbookingTime = overbookingTime;
		this.paymentTime = paymentTime;
		this.orderSource = source;
		this.consignee = consignee;
		this.address = address;
		this.cellphone = cellphone;
		this.postcode = postcode;
		this.purchasing = purchasing;
        this.orderStatus = orderStatus;
        this.paymentStatus = paymentStatus;
        this.deliveryStatus = deliveryStatus;
        this.orderAmount = orderAmount;
        this.goodsAmount = goodsAmount;
        this.paymentAmount = paymentAmount;
        this.discountAmount = discountAmount;
        this.redpacketsAmount = redpacketsAmount;
        this.couponAmount = couponAmount;
        this.integrationAmount = integrationAmount;
        this.freightAmount = freightAmount;
        this.brandType = brandType;
	}
	
	
	//子订单 有优惠
	public OrderInfo(String orderNumber, String parentNumber, DeliveryStatus deliveryStatus,
			Date deliveryTime, String deliveryNumber,
			BigDecimal orderAmount, BigDecimal goodsAmount,
			BigDecimal paymentAmount, BigDecimal discountAmount,
			BigDecimal redpacketsAmount, BigDecimal couponAmount,
			BigDecimal integrationAmount, BigDecimal freightAmount,
            Brand.BrandType brandType) {
		super();
		this.orderNumber = orderNumber;
		this.parentNumber = parentNumber;
		this.deliveryStatus = deliveryStatus;
		this.deliveryTime = deliveryTime;
		this.deliveryNumber = deliveryNumber;
		this.orderAmount = orderAmount;
		this.goodsAmount = goodsAmount;
		this.paymentAmount = paymentAmount;
		this.discountAmount = discountAmount;
		this.redpacketsAmount = redpacketsAmount;
		this.couponAmount = couponAmount;
		this.integrationAmount = integrationAmount;
		this.freightAmount = freightAmount;
        this.brandType = brandType;
	}
	
	//子订单 无优惠
	public OrderInfo(String orderNumber, String parentNumber,
			DeliveryStatus deliveryStatus, Date deliveryTime,
			String deliveryNumber, BigDecimal orderAmount,
			BigDecimal goodsAmount, BigDecimal paymentAmount,
            Brand.BrandType brandType) {
		super();
		this.orderNumber = orderNumber;
		this.parentNumber = parentNumber;
		this.deliveryStatus = deliveryStatus;
		this.deliveryTime = deliveryTime;
		this.deliveryNumber = deliveryNumber;
		this.orderAmount = orderAmount;
		this.goodsAmount = goodsAmount;
		this.paymentAmount = paymentAmount;
        this.brandType = brandType;
	}

	public OrderInfo() {
		super();
	}


    public OrderInfo updateOrderInfo(){
        OrderInfo orderDB = context.getOrderInfoRepository().findOne(this.getId());
        if(orderDB.getFreightAmount() == null){
            orderDB.setFreightAmount(BigDecimal.valueOf(0));
        }
        if(this.getFreightAmount() == null){
            this.setFreightAmount(BigDecimal.valueOf(0));
        }
        if(orderDB.getFreightAmount().compareTo(this.getFreightAmount())!=0){
            this.setOrderAmount(
                    this.getGoodsAmount().
                            subtract(this.getDiscountAmount() == null ? BigDecimal.valueOf(0) : this.getDiscountAmount())
                            .add(this.getFreightAmount()));
            if(!this.isParent){
                OrderInfo parent = context.getOrderInfoRepository().findByOrderNumber(this.parentNumber).get(0);
                if (parent.getFreightAmount() == null){parent.setFreightAmount(BigDecimal.valueOf(0));}
                if (parent.getDiscountAmount() == null){parent.setDiscountAmount(BigDecimal.valueOf(0));}
                List<OrderInfo> children = context.getOrderInfoRepository().findAllChildsByOrderNumber(this.parentNumber);
                BigDecimal totalFreight = BigDecimal.valueOf(0);
                for(OrderInfo child : children){
                    if(child.getId().equals(this.getId())){
                        totalFreight=totalFreight.add(this.getFreightAmount());
                    }else{
                        totalFreight=totalFreight.add(child.getFreightAmount() == null ?BigDecimal.valueOf(0):child.getFreightAmount());
                    }
                }
                parent.setFreightAmount(totalFreight);
                parent.setOrderAmount(this.getGoodsAmount().subtract(parent.getDiscountAmount()).add(totalFreight));
                context.getOrderInfoRepository().save(parent);
            }
        }
        return context.getOrderInfoRepository().save(this);
    }

    /**
     * 只能查询父订单  子订单无法查询
     * 只是针对后台管理界面上的订单查询（显示的全部是父订单）
     * @param orderSearch
     * @return
     */
	
	public static Specification<OrderInfo> searchByCondition(OrderSearch orderSearch){
		return new Specification<OrderInfo>() {

			@Override
			public Predicate toPredicate(Root<OrderInfo> root,
					CriteriaQuery<?> query, CriteriaBuilder cb) {
				
				Predicate predicate = cb.conjunction();
				
				List<Expression<Boolean>> expressions = predicate.getExpressions();
				
				expressions.add(cb.not(root.get("deleted")));
				expressions.add(cb.isTrue(root.get("isParent")));
				if(orderSearch!=null){
					if(StringUtils.isNotBlank(orderSearch.getOrderInfoNumber())){
						expressions.add(cb.equal(root.<String>get("orderNumber"), orderSearch.getOrderInfoNumber()));
					}
					
					if(StringUtils.isNotBlank(orderSearch.getOrderusername())){
						expressions.add(cb.like(root.<String>get("username"), "%"+orderSearch.getOrderusername()+"%"));
					}
					
					if(StringUtils.isNotBlank(orderSearch.getOrderInfoStatus())){
						switch (orderSearch.getOrderInfoStatus()) {
						case "UNCONFIRMED":
							//待确认   查询待确认 待付款  待发货的订单
							expressions.add(cb.equal(root.<OrderInfo.OrderStatus>get("orderStatus"), OrderInfo.OrderStatus.UNCONFIRMED));
							expressions.add(cb.equal(root.<OrderInfo.PaymentStatus>get("paymentStatus"), OrderInfo.PaymentStatus.NONPAYMENT));
							expressions.add(cb.equal(root.<OrderInfo.DeliveryStatus>get("deliveryStatus"), OrderInfo.DeliveryStatus.NONSHIPPED));
							break;
						case "NONPAYMENT":
							//代付款  查询已确认 待付款的订单
							expressions.add(cb.equal(root.<OrderInfo.OrderStatus>get("orderStatus"), OrderInfo.OrderStatus.CONFIRMED));
							expressions.add(cb.equal(root.<OrderInfo.PaymentStatus>get("paymentStatus"), OrderInfo.PaymentStatus.NONPAYMENT));
							break;
						case "NONSHIPPED":
							//代发货 查询已确认 已付款 待发货 部分发货的订单
							expressions.add(cb.equal(root.<OrderInfo.OrderStatus>get("orderStatus"), OrderInfo.OrderStatus.CONFIRMED));
							expressions.add(cb.equal(root.<OrderInfo.PaymentStatus>get("paymentStatus"), OrderInfo.PaymentStatus.ACCOUNTPAID));
							List<DeliveryStatus> deliveryStatuses = new ArrayList<DeliveryStatus>();
                            deliveryStatuses.add(DeliveryStatus.NONSHIPPED);
                            deliveryStatuses.add(DeliveryStatus.SOMESHIPPED);
                            expressions.add(root.<OrderInfo.DeliveryStatus>get("deliveryStatus").in(deliveryStatuses));
							break;
						case "RECEIVED":
							//已收货 查询已确认 已付款 已收货的订单
							expressions.add(cb.equal(root.<OrderInfo.OrderStatus>get("orderStatus"), OrderInfo.OrderStatus.CONFIRMED));
							expressions.add(cb.equal(root.<OrderInfo.PaymentStatus>get("paymentStatus"), OrderInfo.PaymentStatus.ACCOUNTPAID));
							expressions.add(cb.equal(root.<OrderInfo.DeliveryStatus>get("deliveryStatus"), OrderInfo.DeliveryStatus.RECEIVED));
							break;
						case "CANCEL":
							//取消 查询取消 未付款 未发货的订单
							expressions.add(cb.equal(root.<OrderInfo.OrderStatus>get("orderStatus"), OrderInfo.OrderStatus.CANCEL));
							expressions.add(cb.equal(root.<OrderInfo.PaymentStatus>get("paymentStatus"), OrderInfo.PaymentStatus.NONPAYMENT));
							expressions.add(cb.equal(root.<OrderInfo.DeliveryStatus>get("deliveryStatus"), OrderInfo.DeliveryStatus.NONSHIPPED));
							break;
						case "RETURNS":
							//退货 查询退货 未付款 未发货的订单
							expressions.add(cb.equal(root.<OrderInfo.OrderStatus>get("orderStatus"), OrderInfo.OrderStatus.RETURNS));
							expressions.add(cb.equal(root.<OrderInfo.PaymentStatus>get("paymentStatus"), OrderInfo.PaymentStatus.NONPAYMENT));
							expressions.add(cb.equal(root.<OrderInfo.DeliveryStatus>get("deliveryStatus"), OrderInfo.DeliveryStatus.NONSHIPPED));
							break;
						}
					}
					if(StringUtils.isNotBlank(orderSearch.getIntegral())){
						expressions.add(cb.greaterThan(root.<BigDecimal>get("integrationAmount"), BigDecimal.valueOf(0)));
					}
					
					if(StringUtils.isNotBlank(orderSearch.getNeedShipping())){
						Calendar c = Calendar.getInstance();
						c.add(Calendar.DAY_OF_MONTH, -2);
						c.set(Calendar.HOUR, 0);
						c.set(Calendar.MINUTE, 0);
						c.set(Calendar.SECOND, 0);
						expressions.add(cb.equal(root.<OrderInfo.OrderStatus>get("orderStatus"), OrderInfo.OrderStatus.CONFIRMED));
						expressions.add(cb.equal(root.<OrderInfo.PaymentStatus>get("paymentStatus"), OrderInfo.PaymentStatus.ACCOUNTPAID));
						expressions.add(cb.equal(root.<OrderInfo.DeliveryStatus>get("deliveryStatus"), OrderInfo.DeliveryStatus.NONSHIPPED));
						expressions.add(cb.lessThanOrEqualTo(root.<Date>get("paymentTime"), c.getTime()));
					}
					
					if(StringUtils.isNotBlank(orderSearch.getPurchasing())){
						expressions.add(cb.equal(root.<OrderInfo.Purchasing>get("purchasing"), OrderInfo.Purchasing.ISPURCHASING));
					}
				}
				return query.where(predicate).getRestriction();
			}
		};
	}

    public void changeStatus(OrderOperator orderOperator){
        context.getOrderOperatorRepository().save(orderOperator);
        this.setUpdateStatusTime(new Date());
        if (isParent){
            //如果修改了发货状态  那么其下的所有子订单的发货状态也跟着需要改变 相应的需记录改变状态日志
            if (!this.getDeliveryStatus().name().equals(orderOperator.getDeliveryStatus().name())){
                List<OrderInfo> children = context.getOrderInfoRepository().findAllChildsByOrderNumber(this.orderNumber);
                if (CollectionUtils.isNotEmpty(children)){
                    boolean flag = orderOperator.getDeliveryStatus().name().equals("NONSHIPPED")?true:false;
                    for (OrderInfo child : children){
                        boolean flag2 = false;
                        if (flag){
                            flag2=true;
                            child.setDeliveryTime(null);
                            child.setDeliveryNumber(null);
                        }else{
                            if (!child.getDeliveryStatus().equals(DeliveryStatus.SHIPPED)){
                                flag2=true;
                                child.setDeliveryTime(new Date());
                                child.setDeliveryNumber(orderOperator.getDeliveryNumber());
                            }
                        }
                        if(flag2){
                            child.setUpdateStatusTime(new Date());
                            child.setDeliveryStatus(orderOperator.getDeliveryStatus());
                            OrderOperator operator = new OrderOperator(child.getId(),false,orderOperator.getOrderStatus(),orderOperator.getPaymentStatus(),orderOperator.getDeliveryStatus());
                            context.getOrderOperatorRepository().save(operator);
                        }
                    }
                }
            }
            //修改了是否付款
            if (!this.getPaymentStatus().name().equals(orderOperator.getPaymentStatus().name())){
                List<OrderInfo> children = context.getOrderInfoRepository().findAllChildsByOrderNumber(this.orderNumber);
                boolean flag = orderOperator.getPaymentStatus().name().equals("ACCOUNTPAID")?false:true;
                //先设置父订单
                if (flag){//修改为未付款
                    this.setPaymentAmount(BigDecimal.valueOf(0));
                    this.setPaymentTime(null);
                }else{//修改为付款
                    this.setPaymentTime(new Date());
                    this.setPaymentAmount(
                            this.getOrderAmount()
                                    .subtract(this.getIntegrationAmount()==null?BigDecimal.valueOf(0):this.getIntegrationAmount())
                                    .subtract(this.getRedpacketsAmount()==null?BigDecimal.valueOf(0):this.getRedpacketsAmount())
                                    .subtract(this.getCouponAmount()==null?BigDecimal.valueOf(0):this.getCouponAmount())
                    );
                }
                //处理该父订单下的子订单
                if (CollectionUtils.isNotEmpty(children)){
                    for(OrderInfo child:children){
                        if (flag){//修改为未付款
                            child.setPaymentAmount(BigDecimal.valueOf(0));
                            child.setPaymentTime(null);
                        }else{//修改为付款
                            child.setPaymentTime(new Date());
                            child.setPaymentAmount(
                                    child.getOrderAmount()
                                            .subtract(child.getIntegrationAmount() == null ? BigDecimal.valueOf(0) : child.getIntegrationAmount())
                                            .subtract(child.getRedpacketsAmount() == null ? BigDecimal.valueOf(0) : child.getRedpacketsAmount())
                                            .subtract(child.getCouponAmount() == null ? BigDecimal.valueOf(0) : child.getCouponAmount())
                            );
                        }
                        child.setUpdateStatusTime(new Date());
                        OrderOperator operator = new OrderOperator(child.getId(),false,orderOperator.getOrderStatus(),orderOperator.getPaymentStatus(),orderOperator.getDeliveryStatus());
                        context.getOrderOperatorRepository().save(operator);
                    }
                }

            }
            //最后修改父订单的状态
            this.setOrderStatus(orderOperator.getOrderStatus());
            this.setPaymentStatus(orderOperator.getPaymentStatus());
            this.setDeliveryStatus(orderOperator.getDeliveryStatus());

        }else{
            this.setDeliveryStatus(orderOperator.getDeliveryStatus());
            List<OrderInfo> children = context.getOrderInfoRepository().findAllChildsByOrderNumber(this.parentNumber);
            OrderInfo parent = context.getOrderInfoRepository().findByOrderNumber(this.parentNumber).get(0);
            if (orderOperator.getDeliveryStatus().name().equals("NONSHIPPED")){//未发货
                this.setDeliveryTime(null);
                DeliveryStatus deliveryStatus1 = DeliveryStatus.NONSHIPPED;
                for (OrderInfo child : children){
                    if ( !child.getId().equals(this.getId()) && (child.getDeliveryStatus().name().equals("SHIPPED") ||child.getDeliveryStatus().name().equals("RECEIVED"))){
                        deliveryStatus1 = DeliveryStatus.SOMESHIPPED;
                        break;
                    }
                }
                parent.setDeliveryStatus(deliveryStatus1);
            }else{//发货
                this.setDeliveryNumber(orderOperator.getDeliveryNumber());
                this.setDeliveryTime(new Date());
                DeliveryStatus deliveryStatus1 = DeliveryStatus.SHIPPED;
                for (OrderInfo child :children){
                    if (!child.getId().equals(this.getId()) && child.getDeliveryStatus().name().equals("NONSHIPPED")){
                        deliveryStatus1 = DeliveryStatus.SOMESHIPPED;
                        break;
                    }
                }
                parent.setDeliveryStatus(deliveryStatus1);
            }
            OrderOperator operator = new OrderOperator(parent.getId(),true,parent.getOrderStatus(),parent.getPaymentStatus(),parent.getDeliveryStatus());
            context.getOrderOperatorRepository().save(operator);
        }
    }


	
}
